#pragma once
#include <mydll.h>
#include <micro.hxx>
#include <list>
#include <string>
#include <map>
#include <set>
#include <curl/curl.h>
#include <mymutex.hxx>
#include "utility.hxx"

using namespace std;
using namespace Utility;

class FileLog;
class GisusDB;
class Cordinator;
class Keyword;
class User;

class EXPORT Task
{
public:
	typedef map<string, string> ClientInfos;

	typedef enum{
		NEW_CAR_CHOOSE_NO = 0,
		INUSE_CAR_CHOOSE_NO = 1,
		YU_YUE_KAO_SHI = 2
	}TaskType;
	typedef enum{
		NONE = 0,
		REGISTER,
		REFRESH_CAPTCHA,
		QUERY,
		WATCH,
		PICKING1,
		PICKING2,
		REFRESH,
		LOGIN,
		INPUT_CAPTCHA,
		CONFIRM,
		CHGPWD
	}ActionType;
	typedef enum
	{
		SUCCEEDED = 0,
		CREATED = 1,
		LOADED = 2,
		REGISTRRED,
		PICKING1ED,
		INVALID_TASK,
		ZOMBIE_SEED,
		CON_INUSE,
		DELETED,
		HOT_SEED,
		FROZEN,
		LOGINED,	// special for YKTask.
		CONFIRMED
	}TaskStatus;
	typedef enum{
		ACTION_RESULT_NONE,
		ACTION_RESULT_SUCCEEDED,
		ACTION_RESULT_INVALID_INFO,
		ACTION_RESULT_CAPTCHA_WRONG,
		ACTION_RESULT_NO_FOUND,
		ACTION_RESULT_GRAP_FAILED,
		ACTION_RESULT_GRAP_WRONG,
		ACTION_RESULT_NETWORK_ERROR,
		ACTION_RESULT_SESSION_EXPIRED,
		ACTION_RESULT_SERVER_ERROR,
		ACTION_RESULT_TASK_FROZEN,
		ACTION_RESULT_TASK_CON_INUSE,
		ACTION_RESULT_COOKIE_GGG,
		ACTION_RESULT_ALREADY_DONE
	}ActionResult;

	Task(Task::TaskType type, FileLog* filelog = 0);
	Task(const User* user, int id, const string& taskInfo, TaskStatus status = LOADED, Task::TaskType type = NEW_CAR_CHOOSE_NO, FileLog* filelog = 0);
	Task(const Task& model);
	~Task();

	virtual int SaveTask(void);
	virtual bool Update(void);
	virtual bool Delete(void);

	virtual void PreAction(void);
	virtual void Execute(void) = 0;
	virtual void AfterAction(void);
	virtual bool AdjustStatus(void);
	virtual bool IsExpired(void);
	virtual bool IsExpiring(void);

	string StatusDes(void) const;
	void FormPromptMsg(void);

	virtual Task::ActionType NextAction() = 0;
	virtual Task::ActionResult RefreshCaptcha(void) = 0;
	virtual Task::ActionResult Query(void) = 0;
	virtual Task::ActionResult Refresh(void){return Task::ACTION_RESULT_NONE;}

	virtual string Signature(void) const = 0;

	virtual bool SetCaptcha(const string& captcha);
	virtual bool IsCaptchaed(void) const;

	char* GetCaptcha(size_t& size) const;
	string ToString() const;
	bool ResetCaptcha(void);

	void SetFileLog(FileLog* filelog);
	void SetCordinator(Cordinator* cordinator);
	void SetGisusDB(GisusDB* gisusdb);

	bool MarkStatus(bool isZombie=false);

	/* Getters for detailed infos. */
	PROPERTY_TASKINFO(promptmsg);
	PROPERTY_TASKINFO(errmsg);
	PROPERTY_TASKINFO(cjh);
	PROPERTY(PromptLevel, int);

	PROPERTY(Owner, const User*);
	PROPERTY(Id, int);
	PROPERTY(Type, TaskType);
	PROPERTY(Status, TaskStatus);
	PROPERTY(ActionRes, ActionResult);
	PROPERTY(CurAction, ActionType);
	PROPERTY(Port, std::string);

protected:

	stringstream bodystream;
	stringstream captchastream;
	string captcha;

	Cordinator* cordinator;
	GisusDB* gisusdb;
	CURL* curl;
	Mutex curlInUse;

	mutable ClientInfos clientInfos;

	time_t whenLastActivated;

	FileLog* _filelog;
	
	void Parse(const std::string& taskInfo);

	void UpdateLastActivated(void);
	static string GetViewState(const std::stringstream& bodystream);
	static string GetEventValidation(const std::stringstream& bodystream);
	static void DumpFile(const std::stringstream& bodystream, const string& filename, bool isimage= false);

protected:
	string Url;
	string FirstPage;
	string QueryPage;
	string CaptchaPage;
};